/*****************************************************************************
 *  ENTROPY - emerging network to reduce orwellian potency yield
 *
 *  Copyright (C) 2002 Juergen Buchmueller <pullmoll@stop1984.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: osd.h,v 1.6 2005/07/12 23:19:26 pullmoll Exp $
 *****************************************************************************/
#ifndef	_osd_h_
#define	_osd_h_

#include "config.h"
#include "funclib.h"

/* get rid of PACKED attributes alltogether */
#undef	PACKED
#define	PACKED

#ifdef	__CYGWIN__	/* CYGWIN */

#include <errno.h>
#include <stdarg.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/wait.h>
#if	HAVE_MMAP
#include <sys/mman.h>
#endif
#include <sys/utsname.h>

#include <w32api/windows.h>
#include <w32api/winbase.h>

/****************************************************************************
 * process
 */
#define	osd_proc_init(argc,argv) proc_init(argc,argv)
#define	osd_proc_exit() proc_exit()
#define	osd_proc_add(pid,name) proc_add(pid,name)
#define	osd_proc_del(pid) proc_del(pid)
#define	osd_closeall(fd,keepfd) closeall(fd,keepfd)
#define	osd_daemon(nochdir,noclose) daemon(nochdir,noclose)
#define	osd_fork2(name,niceness,keepfd) fork2(name,niceness,keepfd)
#define	osd_sleep(secs) sleep(secs)

/****************************************************************************
 * socket
 */
#define	osd_socket(domain,type,protocol) socket(domain,type,protocol)
#define	osd_send(sk,buff,size) write(sk,buff,size)
#define	osd_recv(sk,buff,size) read(sk,buff,size)
#define	osd_shutdown(sk,how) shutdown(sk,how)
#define	osd_closesocket(sk) close(sk)
#define	osd_fcntl2(fd,cmd) fcntl(fd,cmd)
#define	osd_fcntl3(fd,cmd,flag) fcntl(fd,cmd,flag)

#else	/* !__CYGWIN__ */

#include <errno.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/wait.h>
#if	HAVE_MMAP
#include <sys/mman.h>
#endif
#include <sys/utsname.h>

/****************************************************************************
 * process
 */
#define	osd_proc_init(argc,argv) proc_init(argc,argv)
#define	osd_proc_exit() proc_exit()
#define	osd_proc_add(pid,name) proc_add(pid,name)
#define	osd_proc_del(pid) proc_del(pid)
#define	osd_closeall(fd,keepfd) closeall(fd,keepfd)
#define	osd_daemon(nochdir,noclose) daemon(nochdir,noclose)
#define	osd_fork2(name,niceness,keepfd) fork2(name,niceness,keepfd)
#define	osd_sleep(secs) sleep(secs)

/****************************************************************************
 * socket
 */
#define	osd_socket(domain,type,protocol) socket(domain,type,protocol)
#define	osd_send(sk,buff,size) write(sk,buff,size)
#define	osd_recv(sk,buff,size) read(sk,buff,size)
#define	osd_shutdown(sk,how) shutdown(sk,how)
#define	osd_closesocket(sk) close(sk)
#define	osd_fcntl2(fd,cmd) fcntl(fd,cmd)
#define	osd_fcntl3(fd,cmd,flag) fcntl(fd,cmd,flag)

#endif	/* !__CYGWIN__ */

/* ----------------- shared between *nix and cygwin ----------------- */

#include "expat.h"
#include "zlib.h"

/* System V shared memory and semaphore functions */
#if	HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#if	HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#if	HAVE_SYS_SEM_H
#include <sys/sem.h>
#endif

#if	HAVE_SOCKLEN_T
typedef socklen_t osd_socklen_t;
#else
typedef int osd_socklen_t;
#endif

#ifndef	O_BINARY
#define	O_BINARY	0
#endif

#include "settings.h"

#if	USE_POSIX_SEMAPHORES

#include <semaphore.h>

typedef struct osd_sem_s {
	sem_t posix;
	pid_t pid;
	uint32_t magic;
}	osd_sem_t;

#elif	USE_SVID_SEMAPHORES

/*
 * g_crypto	1
 * g_news	1
 * g_peer	5
 * g_proc	1
 * g_proxy	1
 * g_shm	1
 * g_store	1
 * TOTAL	11
 */
#define	OSD_SEM_NSEMS	11

typedef struct {
	int semid;
	int nsems;
	int nextsem;
}	osd_sem_global_t;

typedef struct osd_sem_s {
	int semid;
	int semnum;
	pid_t pid;
	uint32_t magic;
}	osd_sem_t;

#elif	USE_FLOCK_SEMAPHORES

#define	OSD_SEM_NSEMS	11

#ifndef	MAXPATHLEN
#define	MAXPATHLEN	256
#endif

typedef struct {
	char filename[MAXPATHLEN];	/* filename like entropy-xxxx.sem */
	int nsems;					/* number of semaphores */
	int nextsem;
}	osd_sem_global_t;

typedef struct osd_sem_s {
	int semnum;					/* semaphore number (0 .. nsems-1) */
	pid_t pid;					/* pid that holds a lock */
	uint32_t magic;
}	osd_sem_t;

#else

typedef struct osd_sem_s {
	int value;
	pid_t pid;
	uint32_t magic;
}	osd_sem_t;

#endif	/* USE_*_SEMAPHORES */

/* ------------------------------------------------------------------ */

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct proc_s {
	pid_t	pid;
	time_t	time;
	char	name[120];
}	proc_t;

#define	MAXPROC	1024
#define	MAXSEM	1024

typedef struct proc_list_t {
	osd_sem_t sem;
	pid_t pgrp;
	proc_t entry[MAXPROC];
}	proc_list_t;

extern proc_list_t *g_proc;

/* Just in case the IPC access modes are not defined */
#ifndef	IPC_R
#define	IPC_R	0400
#endif
#ifndef	IPC_W
#define	IPC_W	0200
#endif

#ifndef	SHM_R
#define	SHM_R	IPC_R
#endif
#ifndef	SHM_W
#define	SHM_W	IPC_W
#endif

extern int verbose;
int info(const char *fmt, ...);
int die(int rc, const char *fmt, ...);
void osd_usleep(int64_t usecs);

void closeall(int fd, int keepfd);
int proc_init(int argc, char **argv);
int proc_exit(void);
int proc_add(pid_t pid, const char *name);
int proc_del(pid_t pid);
int proc_info(int n, proc_t *pproc);
char *proc_name(pid_t pid);

int fork2(const char *name, int niceness, int keepfd);
const char *signal_name(int sig);

void osd_exit(int rc);
int osd_getpagesize(void);

#if	!HAVE_STRTOULL   
#ifndef	ULLONG_MAX
/* first guarantee sign extension to 64 bits; then switch to unsigned */
#define	ULLONG_MAX ((uint64_t)(int64_t)-1)
#endif
uint64_t strtoull(const char *nptr, char **endptr, int base);
#endif

#if	!HAVE_TIMEGM
time_t timegm(struct tm *tm);
#endif

#if	!HAVE_UTIMES
int utimes(const char *file, const struct timeval *times);
#endif

#if	USE_SVID_SEMAPHORES || USE_FLOCK_SEMAPHORES
int osd_sem_global_init(osd_sem_global_t *globals);
void osd_sem_global_destroy(osd_sem_global_t *globals);
#endif	/* USE_SVID_SEMAPHORES */

/* temporarily enable debug code */
#ifndef	DEBUG_SEMAPHORES
#define	DEBUG_SEMAPHORES	0
#endif

#if	DEBUG_SEMAPHORES
#define	SEM_FILELINEARGS	, const char *file, unsigned line
#define	SEM_FILELINECONST	, __FILE__, __LINE__
#define	SEM_FILELINEVARS	file, line
#else
#define	SEM_FILELINEARGS
#define	SEM_FILELINECONST
#define	SEM_FILELINEVARS
#endif

int _osd_sem_init(osd_sem_t *sem, int ps, int val SEM_FILELINEARGS);
int _osd_sem_trywait(osd_sem_t *sem SEM_FILELINEARGS);
int _osd_sem_wait(osd_sem_t *sem SEM_FILELINEARGS);
int _osd_sem_post(osd_sem_t *sem SEM_FILELINEARGS);
int _osd_sem_destroy(osd_sem_t *sem SEM_FILELINEARGS);
#define osd_sem_init(sem,pshared,value) \
	_osd_sem_init(sem, pshared, value SEM_FILELINECONST)
#define osd_sem_trywait(sem) \
	_osd_sem_trywait(sem SEM_FILELINECONST)
#define osd_sem_wait(sem) \
	_osd_sem_wait(sem SEM_FILELINECONST)
#define osd_sem_post(sem) \
	_osd_sem_post(sem SEM_FILELINECONST)
#define osd_sem_destroy(sem) \
	_osd_sem_destroy(sem SEM_FILELINECONST)

#ifdef	__cplusplus
}
#endif	/* !__CYGWIN__ */

#endif	/* !defined(_osd_h_) */
